#pragma once

//封装一个线程库(c++)
#include<iostream>
using namespace std;
#include<unistd.h>
#include<string>
#include<pthread.h>
#include<functional>
#include<assert.h>


class Thread;

//这个类里面相当于模仿了this指针还有第4个参数
class Context
{
public:
    Thread* _this;
    void* _args;
public:
    Context():_this(nullptr),_args(nullptr){

    }
    ~Context(){

    }
};





//Thread(func,args,number):执行后会直接调用start_routine函数，并且打印出来name
class Thread{
public:
    typedef function<void*(void*)> fun_c;

    Thread(fun_c func,void* args=nullptr,int number = 0):_func(func),_args(args){
        char buffer[1024];
        snprintf(buffer,sizeof buffer,"%s:%d","thread",number);
        _name = buffer;


        //直接调用pthread_create来构造
        //pthread_create需要的是一个指向静态函数的指针，而不是成员函数
        Context* ctx = new Context();
        ctx->_this=this;
        ctx->_args=_args;
        int n = pthread_create(&_tid,nullptr,start_routine,ctx);
        assert(n == 0);
        (void)n;

    }

    //这里有2个参数，有一个this指针，所以不能这样传参
    //使用静态来修饰，这样就没有this指针了，但是不能去调用成员函数了
    //所以要再封装一个类来去调用成员变量和函数
    static void* start_routine(void* args){//Thread* this,void* _args
     //ctx:this,args
        Context* ctx = static_cast<Context*>(args);
        void* ret = ctx->_this->_func(ctx->_args);
        delete ctx;
        return ret;
    }

    void* run(void* args){
        return _func(args);
    }

    void join(){
        int n = pthread_join(_tid,nullptr);
        assert(n == 0);
        (void)n;
    }
    ~Thread(){

    }



public:
    string _name;//线程执行流打印出来的名称
    pthread_t _tid;//线程的tid
    fun_c _func;//新线程要要调用的执行流
    void* _args;//func的参数
};